package com.wymobilearchitecture.study.thread.security;

import com.example.w_library.log.WLog;

import java.util.ArrayList;
import java.util.List;

/**
 * 锁方法:
 *      加在方法上,未获取到对象锁的其他线程不可以访问该方法
 * 锁CLass对象:
 *      加在 static 方法上相当于给 Class 对象加锁,哪怕是不同的 Java 对象,也需要排队执行
 * 锁代码块:
 *      未获取到对象的锁的其他线程可以执行同步块之外的代码
 */
public class SynchronizedTest {

    private static List<String> tickets = new ArrayList<>();

    public SynchronizedTest(){

        for (int i = 0; i < 5; i++) {
            tickets.add("票 :  " + (i + 1));
        }

        sellTickets();
    }

    private void sellTickets() {

        final  BuyTicket buyTicket = new BuyTicket();
        for (int i = 0; i < 5; i++) {

            new Thread(new Runnable() {
                @Override
                public void run() {
//                    buyTicket.printThreadName();
                    /**
                     * 不同对象的情况,如果只有 synchronized 没有 static 是无法宝成线程安全的
                     */
                    new BuyTicket().printThreadName();
                }
            }).start();
        }
    }

    static class BuyTicket{
         /**
          * 加在方法上对同一个对象在不同线程调用是有用的,
          * 在不同线程的不同对象是无法保证线程安全的
          */
         static synchronized  void printThreadName(){
            String name = Thread.currentThread().getName();
            WLog.e("买票人 : " + name  + " 正在买票....");

             /**
              * 去掉 static ,作用在代码块
              * 同一个对象调用的情况,可以保证代码块内线程安全,代码块之外的代码会先执行,也就是上面的 log 会直接全部打出
              */
//                synchronized (this){
//                    try {
//                        Thread.sleep(1000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            WLog.e("买票人 : "  +name + " 买到的票是...." + tickets.remove(0));
        }
    }


}
